/**
 * $Id: CMPP20MessageConvertor.java,v 1.1 2006/09/22 07:57:09 martin Exp $
 *
 * Copyright 2005 Skyinfo, Inc. All Rights Reserved.
 */
package com.haoxi.gateway.messageconvertor.impl;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


import com.haoxi.gateway.cmppmsg.CMPPDeliverMessage;
import com.haoxi.gateway.cmppmsg.CMPPSubmitRepMessage;
import com.haoxi.gateway.cmppmsg.CMPPSubmitMessage;
import com.haoxi.gateway.cmppmsg.CMPPCommon;
import com.haoxi.gateway.cmpp30msg.CMPPStatusRpt;
import com.haoxi.gateway.common.CommonMsgBean;
import com.haoxi.gateway.common.INFOConst;
import com.haoxi.gateway.common.InitGatewayConfig;
import com.haoxi.gateway.common.SYSConst;
import com.haoxi.gateway.common.Text;
import com.haoxi.gateway.messageconvertor.MessageConvertor;
import com.haoxi.gateway.runner.RunnerMgr;
import com.haoxi.gateway.runner.smscommand.BaseCommandObj;
import com.haoxi.gateway.runner.smscommand.CommandMOResp;
import com.haoxi.gateway.runner.smscommand.CommandReportResp;
import com.haoxi.gateway.runner.smscommand.SubmitCmd;
import com.haoxi.gateway.runner.smscommand.SubmitReportCmd;
import com.haoxi.gateway.runner.smscommand.SubmitStatusCmd;
import com.haoxi.gateway.runner.smscommand.UserMOCmd;


public class CMPP20MessageConvertor extends MessageConvertor {
    private String protcolVersion;
    private static final Log log = LogFactory
            .getLog(CMPP20MessageConvertor.class);
    private static final String SPLITREX = ",";
    private static final byte MSG_LEVEL = 1;
    private static final char[] SPECIAL_CHAR = { '\'' };

    public CMPP20MessageConvertor(String gatewayCode) {
        super(gatewayCode);
        this.protcolVersion = InitGatewayConfig.getInstance().getGatewayInfo()
                .getProtocolVersion();
    }

    public CommonMsgBean convertCMDToCommonMsg(BaseCommandObj obj) {
        CommonMsgBean commonMsgBean = new CommonMsgBean();
        commonMsgBean.setGateWayCode(gatewayCode);
        String icpID = RunnerMgr.getInstance().getGatewayInfo().getIcp_id();
        try {
            if (obj instanceof SubmitCmd) {
                SubmitCmd subCmd = (SubmitCmd) obj;
                int pk_Total = 1;
                int pk_Number = 1;
                int registered_Delivery = subCmd.getReg_del();
                String service_Id = subCmd.getServiceId();
                int fee_UserType = subCmd.getFeeUserType();
                String fee_Terminal_Id = subCmd.getFeeMobile();
                int fee_Terminal_Type = subCmd.getFeeMobileType();
                int tp_Pid = subCmd.getTpPId();
                int tp_Udhi = subCmd.getTpUdhi();
                //int msg_Fmt = subCmd.getMsgCoding();
                int msg_Fmt = 15;
                String fee_Type = subCmd.getFeeType();
                String fee_Code = String.valueOf(subCmd.getFeeCode());
                if (fee_Code.length() < 6) {
                    String tmp = "000000";
                    fee_Code = tmp.substring(0, 6 - fee_Code.length())
                            + fee_Code;
                }
                Date valid_Time = null;
                Date at_Time = null;
                String src_Terminal_Id = subCmd.getOrgMobile();
                String[] dest_Terminal_Id = subCmd.getDestMobile().split(",");
                int dest_Terminal_Type = subCmd.getDestMobileType();
                String content = subCmd.getMsgContent();
                byte[] msg_Content = null;
                int stype = subCmd.getStype();
                // PUSH转码
                if (stype == 200 || stype == 400) {
                    String strPos = "|~@$%^&~|";
                    String url = "";
                    String name = "";
                    int pos = content.indexOf(strPos);
                    url = content.substring(0, pos);
                    name = content.substring(pos + 9);
                    log.debug("push url:" + url);
                    log.debug("push name:" + name);
                    String pdu = getPushPdu(url, name);
                    msg_Content = convertStringToBytes(pdu);
                } else {
                    msg_Content = Text.textToByte(msg_Fmt, content);
                }
                //msg_Content = "content si".getBytes();
                String linkID = subCmd.getLinkID();
                subCmd.setMsgContent(convertSpecialChar(content));
                
                CMPPSubmitMessage submitMsg = new  CMPPSubmitMessage(pk_Total, pk_Number, 
                        registered_Delivery, MSG_LEVEL,service_Id, fee_UserType, fee_Terminal_Id,
                        tp_Pid, tp_Udhi, msg_Fmt, icpID,fee_Type, fee_Code, valid_Time, at_Time,
                        src_Terminal_Id, dest_Terminal_Id,msg_Content, "yes");
                CMPPCommon.setMobileSequence(submitMsg);
                subCmd.setSequence(String.valueOf(submitMsg.getSequenceId()));
                // 打印原始消息
                log.debug(submitMsg);
                commonMsgBean.setBody(submitMsg.getBytes());
                commonMsgBean.setReserve(subCmd);
            }
        } catch (Exception ex) {
            if (null != obj) {
                log.error("baseObj : " + obj.toString());
            } else {
                log.error("baseObj is null !!!");
            }
            log
                    .error(
                            "Exception in CMPP30MessageConvertor.convertCMDToCommonMsg(): Exception",
                            ex);
            commonMsgBean = null;
        }
        return commonMsgBean;
    }

    
    private String getMsgId(byte[] bytes) {
        long lontmp = (long) bytes[7] & (long) 255
                | ((long) bytes[6] & (long) 255) << 8
                | ((long) bytes[5] & (long) 255) << 16
                | ((long) bytes[4] & (long) 255) << 24
                | ((long) bytes[3] & (long) 255) << 32
                | ((long) bytes[2] & (long) 255) << 40
                | ((long) bytes[1] & (long) 255) << 48 | (long) bytes[0] << 56;
        String tmp = "";
        tmp = Long.toBinaryString(lontmp);
        // 不足64位前补0操作
        if (tmp.length() < 64) {
            String tmp0 = "000";
            tmp = tmp0.substring(0, 64 - tmp.length()) + tmp;
        }
        StringBuffer temp = new StringBuffer();
        // 对二进制串进行分割后得到最终需要的字符串
        int month = Integer.parseInt(tmp.substring(0, 4), 2);
        int day = Integer.parseInt(tmp.substring(4, 9), 2);
        int hour = Integer.parseInt(tmp.substring(9, 14), 2);
        int min = Integer.parseInt(tmp.substring(14, 20), 2);
        int sec = Integer.parseInt(tmp.substring(20, 26), 2);
        int gatewaycode = Integer.parseInt(tmp.substring(26, 48), 2);
        int seq = Integer.parseInt(tmp.substring(48), 2);
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DATE, day);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, min);
        calendar.set(Calendar.SECOND, sec);
        SimpleDateFormat dateformat = new SimpleDateFormat("MMddHHmmss");
        Date date = calendar.getTime();
        tmp = dateformat.format(date);
        temp.append(tmp).append(gatewaycode).append(seq);
        return temp.toString();
    }

    public BaseCommandObj convertCommonMsgToCMD(CommonMsgBean commonMsgBean) {
//        BaseCommandObj result = null;
//        Object reserve = commonMsgBean.getReserve();
//        String connName = commonMsgBean.getConnName(); // 记录连接
//        byte[] body = commonMsgBean.getBody();
//        /* 消息头 */
//        byte tmp[] = new byte[4];
//        System.arraycopy(body, 0, tmp, 0, 4);
//        // 消息长度
//        int commandLength = CMPPCommon.Bytes4ToInt(tmp);
//        System.arraycopy(body, 4, tmp, 0, 4);
//        // 消息命令
//        int commid = CMPPCommon.Bytes4ToInt(tmp);
//        System.arraycopy(body, 8, tmp, 0, 4);
//        // 消息序列号
//        int sequence_ID = CMPPCommon.Bytes4ToInt(tmp);
//
//        /* end消息头 */
//        tmp = new byte[commandLength - CMPPCommon.MSG_HEAD_LENGTH];
//        System.arraycopy(body, CMPPCommon.MSG_HEAD_LENGTH, tmp, 0, tmp.length);
        String connName = commonMsgBean.getConnName();
        
        BaseCommandObj result = null;
        int commid = commonMsgBean.getCommid();
        
        if(CMPPCommon.CMPP_DELIVER == commid){
            log.debug("start convert:"+commonMsgBean);
            CMPPDeliverMessage deliverMsg = (CMPPDeliverMessage)commonMsgBean.getReserve();
            log.debug("deliverMsg:"+deliverMsg);
            int commandLength = 8 + deliverMsg.getBytes().length;
            int sequence_ID = deliverMsg.getSequenceId();
            if (1==deliverMsg.getRegisteredDeliver()) {
                CMPPStatusRpt status = new CMPPStatusRpt(deliverMsg.getMsgContent());
                result = convertToSubmitReportCmd(commid, commandLength,
                        sequence_ID, deliverMsg, status, connName, deliverMsg
                                .getMsgId());
                log.debug("status:"+status);
            } else {
                // 处理UserMO消息
                result = convertToUserMOCmd(commid, commandLength, sequence_ID,
                        deliverMsg, deliverMsg, connName);
                
            }
        } else if (CMPPCommon.CMPP_SUBMIT_RESP == commid) {
            CMPPSubmitRepMessage submitReq = (CMPPSubmitRepMessage)commonMsgBean.getReserve(); 
            int sequence_ID = submitReq.getSequenceId();
            int commandLength = 21;
            result = convertToSubmitStatusCmd(commid, commandLength,sequence_ID, submitReq, submitReq);
//            } catch (Exception ex) {
//                result = null;
//                log
//                        .error(
//                                "Exception in CMPP30MessageConvertor.convertCommonMsgToCMD(): Exception",
//                                ex);
//            }
            log.debug("CMPP20MessageConvert:"+result);
        }
        return result;
    }
    /**
     * 把接收到submit report中 byte数组中数据转换为SubmitReportCmd
     * 
     * @param submitReportMsg
     * @return SubmitReportCmd
     * @author martin
     */
    private SubmitReportCmd convertToSubmitReportCmd(int commid,
            int commandLength, int sequence_ID, Object reserve,
            CMPPStatusRpt status, String connName, byte[] deliver_MsgId_bytes) {
        SubmitReportCmd report = new SubmitReportCmd();
        report.setCommandID(commid);
        report.setCommandLength(commandLength);
        String msgid = this.getMsgId(status.getMsgIdbytes());
        report.setMsgID(msgid);
        report.setReport(status.getStat());
        report.setReserved(reserve);
        report.setSequence(String.valueOf(sequence_ID));
        report.setUserNumber(status.getDest_terminal_Id());
        // 长号码
        report.setUserNumberType(INFOConst.TRUE_TYPE);
        report.setMsgId_bytes(deliver_MsgId_bytes);
        report.setConnName(connName);// 记录连接
        return report;
    }
    /**
     * 把接收到submit status中 byte数组中数据转换为SubmitStatusCmd
     * 
     * @param submitStatusMsg
     * @return SubmitStatusCmd
     * @author martin
     */
    private SubmitStatusCmd convertToSubmitStatusCmd(int commid,
            int commandLength, int sequence_ID, Object reserve,
            CMPPSubmitRepMessage submitRep) {
        SubmitStatusCmd submitCmd = new SubmitStatusCmd();
        submitCmd.setCommandID(commid);
        submitCmd.setCommandLength(commandLength);

        String msgid = this.getMsgId(submitRep.getMsgId());
        submitCmd.setMsgID(msgid);
        submitCmd.setReserved(reserve);
        submitCmd.setSequence(String.valueOf(sequence_ID));
        submitCmd.setStatus(String.valueOf(submitRep.getResult()));

        return submitCmd;
    }

    /**
     * 把接收到user Mo byte数组中数据转换为UserMOCmd 解析deliver消息
     * 
     * @param msgBean
     * @return
     */
    private UserMOCmd convertToUserMOCmd(int commid, int commandLength,
            int sequence_ID, Object reserve, CMPPDeliverMessage deliverMsg,
            String connName) {
        UserMOCmd mocmd = new UserMOCmd();
        // 消息命令字
        mocmd.setCommandID(commid);
        // 消息长度
        mocmd.setCommandLength(commandLength);
        // 目标号码
        mocmd.setDestMobile(deliverMsg.getDestnationId());
        // 目的号码的类型0--真实号码1--伪码CMPP30协议中未规定，这里直接填0
        mocmd.setDestMobileType(INFOConst.TRUE_TYPE);
        // 网关编码
        mocmd.setGateWayCode(gatewayCode);
        // 点播业务使用的LinkID，非点播类业务的MT流程不使用该字段
        //mocmd.setLinkId(deliverMsg.getLinkID());
        // 消息编码
        int msgFormat = deliverMsg.getMsgFmt();
        mocmd.setMsgCoding(msgFormat);
        // 消息内容
        String msgContent = Text.getText(msgFormat, deliverMsg.getMsgContent());
//        String msgContent = null;
//        try{
//            msgContent = new String(deliverMsg.getMsgContent(),"unicodeBig");
//        }catch(UnsupportedEncodingException ue){
//            log.error(ue.getMessage());
//        }
        
        mocmd.setMsgContent(msgContent);
        // 消息ID
        byte[] msgDdBytes = deliverMsg.getMsgId();
        String msgId = this.getMsgId(msgDdBytes);
        // for (int i = 0; i < msgDdBytes.length; i++) {
        // msgId += msgDdBytes[i];
        // }
        // String msgId =
        // String.valueOf(Common.BytesToInt(deliverMsg.getMsgId()));
        mocmd.setMsgId(msgId);
        // 源终端MSISDN号码（状态报告时填为CMPP_SUBMIT消息的目的终端号码）
        mocmd.setOrgMobile(deliverMsg.getSrcterminalId());
        // 源终端号码类型，0：真实号码；1：伪码
        //mocmd.setOrgMobileType(deliverMsg.getSrc_Terminal_Type());
        // 移动的CMPP30协议中取消了保留字段，填空
        mocmd.setReserved(reserve);
        // 消息序列号
        mocmd.setSequence(String.valueOf(sequence_ID));
        // 业务编号
        mocmd.setServiceId(deliverMsg.getServiceId());
        // 移动CMPP没有SP编号，这里填目的号码
        //mocmd.setSpNumber(deliverMsg.getDest_id());
        mocmd.setSpNumber(deliverMsg.getDestnationId());
        mocmd.setMsgId_bytes(deliverMsg.getMsgId());
        mocmd.setConnName(connName); // 记录连接
        return mocmd;
    }

    public String getProtcolVersion() {
        return protcolVersion;
    }
    public String getPushPdu(String pushUrl, String pushName) {
        StringBuffer pdu = new StringBuffer();
        pdu.append("0605040B8423F0");
        pdu.append("DC0601AE02056A0045C60C03");
        // 将网址转换到UTF8进制
        pdu.append(stringToUTF8(handleUrl(pushUrl)));
        pdu.append("000103");
        // 将网址名字转换到utf8编码
        pdu.append(stringToUTF8(pushName));
        pdu.append("000101");
        return pdu.toString().toUpperCase();
    }
    public String handleUrl(String url) {
        String handleUrl = "";
        String head = "http://";
        try {
            if (url.indexOf(head) != -1) // 如果有http://头部，则除去头部
            {
                handleUrl = url.substring(head.length());
            } else // 返回原值
            {
                handleUrl = url;
            }

            return handleUrl;
        } catch (Exception ex) {

        }

        return handleUrl;
    }

    public String stringToUTF8(String s) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (c >= 0 && c <= '\377') {
                String hex = Integer.toHexString(c).length() >= 2 ? Integer
                        .toHexString(c) : "0" + Integer.toHexString(c);
                sb.append(hex);
            } else {
                byte b[];
                try {
                    b = Character.toString(c).getBytes("UTF-8");
                } catch (Exception ex) {
                    log.error("", ex);
                    b = new byte[0];
                }
                for (int j = 0; j < b.length; j++) {
                    int k = b[j];

                    if (k < 0) {
                        k += 256;
                    }
                    sb.append(Integer.toHexString(k).toUpperCase());
                }

            }
        }

        return sb.toString().toUpperCase();
    }

    public byte[] convertStringToBytes(String srcBuff) {
        byte dest[] = (byte[]) null;
        try {
            dest = new byte[srcBuff.length() / 2];
            int j = 0;
            for (int i = 0; i < srcBuff.length();) {
                String subBuff = srcBuff.substring(i, i + 2);
                byte ab = (byte) Integer.parseInt(subBuff, 16);
                dest[j] = ab;
                i += 2;
                j++;
            }

            return dest;
        } catch (Exception exception) {
            return dest;
        }
    }
    public String convertSpecialChar(String temp) {
        String result = "";
        if (SPECIAL_CHAR.length > 0) {
            for (int i = 0; i < SPECIAL_CHAR.length; i++) {
                int j = temp.indexOf(SPECIAL_CHAR[i]);
                while (-1 != j) {
                    result += temp.substring(0, j) + "/"
                            + Character.toString(SPECIAL_CHAR[i]);
                    temp = temp.substring(j + 1);
                    j = temp.indexOf(SPECIAL_CHAR[i]);
                }
                result += temp;
                temp = result;
            }
        }
        return result;
    }
}
